package com.mijie.homi.ns.core.handler;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.mina.core.session.IoSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mijie.core.ApplicationProperties;
import com.mijie.core.Status;
import com.mijie.homi.common.constant.HomiStatusCode;
import com.mijie.homi.common.constant.TypeCode;
import com.mijie.homi.common.domain.Upgrade;
import com.mijie.homi.common.domain.mood.Mood;
import com.mijie.homi.common.domain.mood.MoodInfo;
import com.mijie.homi.common.domain.user.Setting;
import com.mijie.homi.common.domain.user.ThirdPartAccount;
import com.mijie.homi.common.domain.user.User;
import com.mijie.homi.common.domain.user.UserExtInfo;
import com.mijie.homi.common.protocol.HomiProtocol;
import com.mijie.homi.common.util.HomiUtil;
import com.mijie.homi.ns.core.HomiServer;
import com.mijie.homi.ns.domain.Constants;
import com.mijie.homi.ns.service.MoodService;
import com.mijie.homi.ns.service.SessionService;
import com.mijie.homi.ns.service.UpgradeService;
import com.mijie.homi.ns.service.UserService;
import com.mijie.util.DateUtil;
import com.mijie.util.Helper;

@Service
public class LoginHandler implements Handler {

	@Autowired
	private UserService userService;
	@Autowired
	private SessionService sessionService;
	@Autowired
	private MoodService moodService;
	@Autowired
	private UpgradeService upgradeService;
	@Autowired
	private HomiServer homiServer;
	
	
	@Override
	public Object handler(IoSession session, HomiProtocol protocol) {
		JSONObject json = JSONObject.fromObject(new String(protocol.getContent()));
		if(json.containsKey("nickName") && json.containsKey("passwd") && 
		   json.containsKey("appVer") && json.containsKey("os")){
			boolean wifi = false;
			if(json.containsKey("wifi") && json.getBoolean("wifi")) wifi = true;
			login(session,json.getString("nickName"),Helper.base64decode(json.getString("passwd")),json.getString("os").toLowerCase(),json.getString("appVer"),wifi);
		}else{
			Status status = new Status();
			status.setMessage("登陆出现异常");
			status.setCode(HomiStatusCode.PARAM_ABSENT);
			HomiProtocol msg = new HomiProtocol(TypeCode.LOGIN);
			msg.setContent(status.toString());
			session.write(msg);
		}
		return null;
	}
	
	private void login(IoSession session,String nickName,String passwd,String os,String appVer,boolean wifi){
		Status status = new Status();
		User user = null;
		if(Helper.isEmail(nickName)){
			user = userService.getUserByEmail(nickName);
		}
		
		if(Helper.isInt(nickName)){
			user = userService.getUserById(Integer.parseInt(nickName));
		}
		
		boolean sendTips = false;
		if(user==null){
			List<User> userList = userService.listUserByNicknameAndPassword(nickName, passwd);
			if (userList.size()==1){
				user = userList.get(0);
				//昵称+密码如果是唯一就让登陆成功，只是为了兼容老版本无法记住帐号密码自动登陆
			}else if(userList.size()>1){
				sendTips = true;
			}
		}
		
		if(user==null){
			if(sendTips){
				status.setMessage("请使用邮箱登录");
			}else{
				status.setMessage("账号或密码不正确");
			}
			status.setCode(HomiStatusCode.USER_NOT_FOUND);
		}else{
			if(user.getBlock().equals(1)){
				status.setMessage("该账户已经禁止登陆");
				status.setCode(HomiStatusCode.USER_BLOCKED);
			}else{
				if(!user.getPasswd().equals(passwd)){
					status.setMessage("密码错误");
					status.setCode(HomiStatusCode.PASSWORD_ERROR);
				}else{
					long oldSessionId = sessionService.getIoSessionIdByUserId(user.getId());
					if(oldSessionId>0){
						//已经登陆 
						final IoSession oldSession = homiServer.getIoSessionById(oldSessionId);
						if(oldSession!=null && user!=null && passwd!=null && user.getPasswd().equals(passwd)){
							oldSession.write(new HomiProtocol(TypeCode.KICKED));
							oldSession.close(false);
							String oldToken = (String) oldSession.getAttribute(Constants.KEY_TOKEN);
							HomiServer.INFO("be forced to logout:userId->"+oldSession.getAttribute(Constants.KEY_USER_ID)+",mina session id->"+oldSession.getId());
						}
					}
					
					String token = sessionService.createSession(user,session.getId(),os,appVer);
					session.setAttribute(Constants.KEY_USER_ID, user.getId());
					session.setAttribute(Constants.KEY_TOKEN,token);
					session.setAttribute(Constants.KEY_OS,os);
					session.setAttribute(Constants.KEY_APPVER,appVer);
					
					userService.deleteUserInfoSubcribe(user.getId());//重置订阅,退出和登陆都重置一次
					UserExtInfo info = userService.getUserExtInfoByUserId(user.getId());
					Mood recentlyMood = moodService.getRecentlyMood(user.getId());
					boolean isFirstTimeLoginOfToday = true;
					if(recentlyMood!=null) 
						isFirstTimeLoginOfToday = !DateUtil.isSameDay(recentlyMood.getCreateAt(), new Date());
					
					SocketAddress remoteAddr = session.getRemoteAddress();
					String clientIP = null;
					if(remoteAddr!=null)
						clientIP = ((InetSocketAddress)remoteAddr).getAddress().getHostAddress();
					userService.updateLastLoginAt(info.getId(),os,info.getDeviceId(),clientIP==null?"":clientIP);
					
					JSONObject result = new JSONObject();
					result.accumulate(Constants.KEY_USER_ID, user.getId());
					result.accumulate(Constants.KEY_TOKEN, token);
					result.accumulate("avatar", user.getAvatar().trim().isEmpty()?"":ApplicationProperties.get("resource.url")+user.getAvatar());
					if(info.getAlbumCover().trim().isEmpty()){
						result.accumulate("albumCover","");
					}else{
						result.accumulate("albumCover", info.getAlbumCover().startsWith("recommend_")?info.getAlbumCover():ApplicationProperties.get("resource.url")+info.getAlbumCover());
					}
					
					if(recentlyMood==null){
						result.accumulate("lastMoodId", 0);
						result.accumulate("lastMood", 0);
						result.accumulate("moodUpdateAt", 0);
						result.accumulate("moodContent", "");
					}else{
						result.accumulate("lastMoodId", recentlyMood.getId());
						result.accumulate("lastMood", recentlyMood.getMood());
						result.accumulate("moodUpdateAt", recentlyMood.getCreateAt().getTime());
						result.accumulate("moodContent", recentlyMood.getContent()==null?"":recentlyMood.getContent());
					}
					result.accumulate("nickName", user.getNickName());
					result.accumulate("email", user.getEmail());
					result.accumulate("gender", user.getGender());
					result.accumulate("isFirstTimeLoginOfToday",isFirstTimeLoginOfToday);
					result.accumulate("firstLoginToday", !DateUtil.isSameDay(new Date(), info.getLastLoginAt()));
					result.accumulate("currentTimeMillis", System.currentTimeMillis());
					Upgrade upgrade = upgradeService.getUpgrade(os,appVer);
					if(upgrade!=null){
						result.accumulate("upgradeSource", ApplicationProperties.get("resource.url")+upgrade.getSource().trim());
						result.accumulate("summarize", upgrade.getSummarize().trim());
					}else{
						result.accumulate("upgradeSource", "");
						result.accumulate("summarize", "");
					}
					
					result.accumulate("thirdPartAccounts", getThirdPartAccount(user.getId()));
					result.accumulate("moodInfoList", getMoodInfo());
					result.accumulate("setting", getSetting(user.getId()));
					status.setResult(result);
					
					homiServer.markUsed(session);
				}
			}
		}
		HomiProtocol msg = new HomiProtocol(TypeCode.LOGIN);
		msg.setContent(status.toString());
		session.write(msg);
	}
	
	private JSONArray getMoodInfo(){
		List<MoodInfo> list = moodService.listMoodInfo();
		JSONArray array = new JSONArray();
		JSONObject json = null;
		for(MoodInfo info : list){
			json = JSONObject.fromObject(info);
			json.put("largeIcon", HomiUtil.getRealUrl(info.getLargeIcon()));
			json.put("smallIcon", HomiUtil.getRealUrl(info.getSmallIcon()));
			array.add(json);
		}
		return array;
	}
	
	private JSONObject getSetting(int userId){
		Setting setting = userService.getSettingByUser(userId);
		if(setting==null){
			HomiServer.ERROR("@@@getSetting fail,userId:"+userId);
			return new JSONObject();
		}
		return JSONObject.fromObject(setting);
	}
	
	private JSONArray getThirdPartAccount(int userId){
		List<ThirdPartAccount> accountList = userService.listThirdPartAccountByUser(userId);
		JSONArray accountJsonArray = new  JSONArray();
		JSONObject accountJson = null;
		ThirdPartAccount ac = null;
		Iterator<ThirdPartAccount> iter = accountList.iterator();
		while(iter.hasNext()){
			ac = iter.next();
			accountJson = new JSONObject();
			accountJson.accumulate("accountId", ac.getAccountId());
			accountJson.accumulate("accessToken", ac.getAccessToken());
			accountJson.accumulate("type", ac.getType());
			accountJsonArray.add(accountJson);
			iter.remove();
		}
		iter = null;
		accountList = null;
		return accountJsonArray;
	}
}
